package org.vectrics.recruiter.struts.tag;

/**
 * @author Mike Moore
 */

import java.text.NumberFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
import java.util.TreeSet;
import java.util.Vector;

import javax.servlet.jsp.JspException;

import org.apache.ecs.Element;
import org.apache.ecs.html.Font;
import org.apache.ecs.html.Form;
import org.apache.ecs.html.IMG;
import org.apache.ecs.html.Input;
import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.common.html.BorderTable;
import org.vectrics.common.html.Cell;
import org.vectrics.common.html.NameValueTable;
import org.vectrics.common.html.Row;
import org.vectrics.common.html.Table;
import org.vectrics.common.html.TextHelper;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.location.Location;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.config.RecruitConfig;
import org.vectrics.recruiter.job.Job;
import org.vectrics.recruiter.job.JobCandidate;
import org.vectrics.recruiter.job.JobCandidateCriteria;
import org.vectrics.recruiter.job.JobFunction;
import org.vectrics.recruiter.job.JobSearchRating;
import org.vectrics.recruiter.struts.admin.JobSearchActionHelper;
import org.vectrics.struts.VectricsTagSupport;
import org.vectrics.user.Person;

public class JobViewTag extends VectricsTagSupport {
	public static final long serialVersionUID = 91588834710277L;

	static private transient Logger log = Logger.getLogger(JobViewTag.class);
	private boolean alwaysShowTravel = false;
    public static String PREV_JOB_PARAM = "prev_job";
    public static String NEXT_JOB_PARAM = "next_job";
    private String jobId = null;
    private String summary = "false";
    private String formName = null;
 
    
    public void setJob(String id) {
    	jobId = id;
    	log.debug("setJob() - set to" + jobId);
    }
    
    
    private boolean isSummary() {
    	if ((summary == null) || (summary.startsWith("tr"))) {
    		return(true);
    	} else
    		return(false);
    }
    
    private Job getJob() {
    	Job job = RecruitServiceLocator.getJobProvider().findJob(new Long(jobId));
    	return(job);
    }

    public String makeStartTag()  {
    	ThreadProperties.forcedCommitAndNewTransaction();
		log.debug("doStartTag() called");

		if (jobId == null) {
			jobId = (String)this.getRequest().getSessionAttribute("currentJobId");
		} else {
			this.getRequest().setSessionAttribute("currentJobId", jobId);
		}
		if (jobId == null) {
			throw new SystemException("Attempt to view job with NULL id");
		}
		
        String prevParam = this.getRequest().getParameter(PREV_JOB_PARAM);
        String nextParam = this.getRequest().getParameter(NEXT_JOB_PARAM);

        
        Table pageTable = new Table();
        try {
	        Row pageRow = pageTable.addRow();
	        Cell leftCell = pageRow.addCell();
	        
	        if (!isSummary()) { 
		        Cell sepCell = pageRow.addCell();
		        sepCell.addElement("&nbsp;");
		        sepCell.setWidth(20);
		        
		        Cell rightCell = pageRow.addCell();
		        rightCell.setWidth(100);
		        IMG clear = new IMG();
		        clear.setSrc(this.getRequest().getContextPath() + "/graphics/cleardot.gif");
		        clear.setWidth(250);
		        clear.setHeight(1);
		        
		        rightCell.setVAlign("top");
		        rightCell.addElement(clear);
		        Table buttonTable = new Table();
		        rightCell.addElement(buttonTable);
		        Row buttonRow = null;
		        Cell buttonCell = null;
		        if (this.getShowJobApplication()) {
			        buttonRow = buttonTable.addRow();
			        buttonCell = buttonRow.addCell();
			        buttonCell.addElement(getApplicationContent());
		        }
		        
				JobSearchActionHelper helper = new JobSearchActionHelper();
		        if (helper.loadCriteria(this.getRequest()) != null) {
			        buttonRow = buttonTable.addRow();
			        buttonCell = buttonRow.addCell();
		        	buttonCell.addElement(getBackToJobListButton());
		        }
		        buttonRow = buttonTable.addRow();
		        buttonCell = buttonRow.addCell();
		        buttonCell.addElement(getJobSearchButton());
	        }
	        
	        log.debug("doRender() - getting http params");
	        Job job = null;
	        
	        
	        if (jobId == null) {
				log.error("doRender() - 'job' param not given");
	            throw new JspException("Job not found.  ID = " + jobId);
	        } else {
	            if (prevParam != null) {
	                jobId = findPreviousJob(new Long(jobId)).toString();
	            }
	            else if (nextParam != null) {
	                jobId = findNextJob(new Long(jobId)).toString();
	            }
	          
	            
	            log.debug("doRender() - 'job' param given looking for job.");
	            if (jobId != null)
	                job = RecruitServiceLocator.getJobProvider().findJob(new Long(jobId));
	            if (job == null) {
	                log.error("doRender() - could not find job param" + jobId);
	            } else {
	            	log.debug("doRender() - found job.");
	                NameValueTable table = new NameValueTable(this.getContextPath() + "graphics/");
	                table.setWidth(500);
	                table.setCellSpacing(0);
	                table.setCellPadding(0);
	                leftCell.addElement(table);
	
					log.debug("doRender() - displaying job information.");
	                
					table.addNameValueRow(this.getPhrase("prompt.job.title"), job.getTitle());
					table.addSepRow(2);

					if ((job.getDescription() != null) && (job.getDescription().length() > 0)) {
	                    table.addNameValueRow(
	                    		this.getPhrase("prompt.job.description"), 
	                    		TextHelper.getHtmlParagraphs("stdFont", job.getDescription())
	                    		);
						table.addSepRow(2);
	                }
					

					Location location = job.getLocation();
					log.debug("doRender() - location.");
					if (location != null) {
						table.addNameValueRow(this.getPhrase("prompt.job.location"), location.getName());
					} else {
						table.addNameValueRow(this.getPhrase("prompt.job.location"), this.getPhrase("not.given"));
					}
					table.addSepRow(2);

					Domain domain = ThreadProperties.getDomain();

					if (RecruitConfig.getRecruitInstance().getShowCompanyOnPublicJobView(domain)) {
						table.addNameValueRow(this.getPhrase("prompt.company"), job.getCompany().getName());
						table.addSepRow(2);
					}

					if (!isSummary()) {
						JobFunction jobFunction = RecruitServiceLocator.getJobProvider().findFunction(job.getFunction().getCode());
						table.addNameValueRow(this.getPhrase("prompt.job.function"), 
								jobFunction.getDescription());
						
						//log.debug("doRender() - date posted.");
						//table.addNameValueRow(this.getPhrase("prompt.job.date.posted"), DateUtil.getDateFormatRoundToDay(this.getLocale()).format(job.getDatePosted()));
						table.addSepRow(2);
		                
		                log.debug("doRender() - displaying salary.");
		                if (job.getSalary() != null) {
		                    NumberFormat numFormat = NumberFormat.getCurrencyInstance(Locale.US);
		                    String phraseCode = "prompt.job.salary";
		                    String salaryStr = numFormat.format(job.getSalary().doubleValue());
		                    if (job.getSalaryMax() != null) {
			                    salaryStr += " to " + numFormat.format(job.getSalaryMax().doubleValue());
			                    phraseCode = "prompt.job.salary.range";
		                    }
							table.addNameValueRow(this.getPhrase(phraseCode), salaryStr);
							table.addSepRow(2);
		                }
		
						log.debug("doRender() - travel percent.");
						String travelPercent = "Not Given";
						if (job.getTravelPercent() != null)
							travelPercent = job.getTravelPercent().toString();
						if (alwaysShowTravel) {
							table.addNameValueRow(this.getPhrase("prompt.job.travel"), travelPercent + " %");
							table.addSepRow(2);
						}
		
		                
		                
						log.debug("doRender() - reference id.");
						if (job.getReferenceId() != null) {
							table.addNameValueRow(this.getPhrase("prompt.job.reference.id") + " ", job.getReferenceId());
							table.addSepRow(2);
						}
		                
						log.debug("doRender() - count.");
						if (job.getReferenceId() != null) {
							table.addNameValueRow(this.getPhrase("prompt.job.number.positions"), 
									job.getCount().toString());
							table.addSepRow(2);
						}
		
		                
		                leftCell.addElement(TextHelper.getFont("stdFont", "<br><br>"));
		                
						log.debug("doRender() - displaying job summary.");
		                if ((job.getSummary() != null) && (job.getSummary().length() > 0)) {
		                    table.addNameValueRow(
		                    		this.getPhrase("prompt.job.summary"), 
		                    		TextHelper.getHtmlParagraphs("stdFont", job.getSummary())
		                    		);
							table.addSepRow(2);
		                }
	
						if ((job.getEducation() != null) && (job.getEducation().length() > 0)) {
		                    table.addNameValueRow(
		                    		this.getPhrase("prompt.job.education"), 
		                    		TextHelper.getHtmlParagraphs("stdFont", job.getEducation())
		                    		);
							table.addSepRow(2);
		                }
		                
		                
		                if (RecruitConfig.getRecruitInstance().getAllowMultipleCompanies(ThreadProperties.getDomain())) {
							log.debug("doRender() - displaying job company info.");
							
	
			                if ((job.getCompanyInfo() != null) && (job.getCompanyInfo().length() > 0)) {
								log.info("doRender() - company info found.");
			                    table.addNameValueRow(
			                    		this.getPhrase("prompt.company.background"), 
			                    		TextHelper.getHtmlParagraphs("stdFont", job.getCompanyInfo())
			                    		);
								table.addSepRow(2);
			                }
		                }
		                
		                                
		                if (RecruitConfig.getRecruitInstance().getSkillsEnabled()) {
							log.debug("doRender() - displaying required skills.");
			                if ((job.getRequiredSkills() != null) && (job.getRequiredSkills().length() > 0)) {
			                    table.addNameValueRow(
			                    		this.getPhrase("prompt.job.required.skills"), 
			                    		TextHelper.getHtmlParagraphs("stdFont", job.getRequiredSkills())
			                    		);
								table.addSepRow(2);
			                }
		                }
		                else {
		                	log.debug("Skills disabled, not showing job skills");
		                }
					}
	                
	            }
	        }
	        log.debug("doRender() - done.");
        }
        catch (Exception ex) {
        	log.error("Exception in JobViewTag ", ex);
        	throw new SystemException(ex.getMessage());
        }
	

		return(pageTable.toString());
    }



    private Long findNextJob(Long jobId) {
        log.info("findNextJob() - called");

        Long nextJobId = null;
        TreeSet sortedJobs = (TreeSet)this.getRequest().getSessionAttribute("job_list");
        if (sortedJobs != null) {
            if (log.isDebugEnabled()) 
                log.debug("findNextJob() - sorted jobs size = " + sortedJobs.size());
              
            Vector jobs = new Vector();
            jobs.addAll(sortedJobs);
            int index = getJobIndex(jobs, jobId); //jobs.indexOf(jobId);
            if ((index >= 0) && (index < jobs.size() - 1)) {
                JobSearchRating nextJobRating = (JobSearchRating)jobs.elementAt(index + 1);
                nextJobId = nextJobRating.getJobId();
            }
            else
                log.debug("findNextJob() - current job id is at end of list - no next  Index = " + index);
        }
        else {
            log.debug("findPreviousJob() - no 'job_list' attribute found for session.  Perhaps no previous search for jobs performed.");
        }
        
        return(nextJobId);
    }

    
    
    private int getJobIndex(Collection jobList, Long jobId) {
    	log.info("getJobIndex() - called");
        Iterator iter = jobList.iterator();
        int index = 0;
        int foundIndex = -1;
        while (iter.hasNext()) {
            JobSearchRating rating = (JobSearchRating)iter.next();
            if (rating.getJobId().equals(jobId)) {
                foundIndex = index;
            }
            index++;
        }
        return(foundIndex);
    }
    

    private Long findPreviousJob(Long jobId) {
        log.info("findPreviousJob() - called");
        Long prevJobId = null;
        TreeSet sortedJobs = (TreeSet)this.getRequest().getSessionAttribute("job_list");

        if (sortedJobs != null) {
            if (log.isDebugEnabled()) 
                log.debug("findNextJob() - sorted jobs size = " + sortedJobs.size());
             
            Vector jobs = new Vector();
            jobs.addAll(sortedJobs);
            int index = getJobIndex(jobs, jobId); //jobs.indexOf(jobId);
            if (index > 0) {
                JobSearchRating prevJobRating = (JobSearchRating)jobs.elementAt(index - 1);
                prevJobId = prevJobRating.getJobId();
            }
            else
                log.debug("findPreviousJob() - current job id is at beginning of list - no previous. Index = " + index);
        }
        else {
            log.debug("findPreviousJob() - no 'job_list' attribute found for session.  Perhaps no previous search for jobs performed.");
        }
            
        return(prevJobId);
    }
    
    /*
     * Show a button allowing the current user to apply for a job.  Show message if user has
     * already applied (or being considered) for job.
     */
    private String getApplicationContent() {
    	StringBuffer html = new StringBuffer();
    	Person person = this.getAuthPerson();
    	if (person != null) {
    		JobCandidateCriteria criteria = new JobCandidateCriteria();
    		criteria.setJob(this.getJob());
    		criteria.setPerson(person);
    		Collection jobCands = RecruitServiceLocator.getJobProvider().findJobCandidates(criteria, 0, 10);
    		if ((this.getJob() != null) && (jobCands.size() <= 0)) {
    			showApplyToJobContent(html, person);
    		} else {
    			Iterator iter = jobCands.iterator();
				JobCandidate jobCand = (JobCandidate)iter.next();
				showAlreadyCandidateContent(html, jobCand);
    		}
    	} else {
			showApplyToJobContent(html, person);
    	}
    	return(html.toString());
    }
    
    private void showApplyToJobContent(StringBuffer html, Person person) {
    	boolean allowApplications = true;
    	if (person != null)
    		allowApplications = RecruitConfig.getRecruitInstance().getAllowApplications(person.getDomain());
    	if (allowApplications) {
	    	Form form = new Form();
	    	form.setMethod(Form.GET);
	    	form.setAction("/hrs-public/profile/" + ThreadProperties.getUriDomainId() 
	    			+ "/job/apply.do");
	    	Input jobHidden = new Input();
	    	jobHidden.setType(Input.HIDDEN);
	    	jobHidden.setName("jobId");
	    	jobHidden.setValue(getJob().getId().toString());
	    	form.addElement(jobHidden);
	    	
			String button ="<input type=\"image\" src=\"" +
				this.getContextPath() +	 "/dynagraphic/button.jpg?code=public.button.wide&caption="
			    + this.getPhrase("phrase.apply.to.job.button") + "\" border=\"0\" value=\"submit\" name=\"submit\" />";
	    	
	    	form.addElement(button);
	    	html.append(form.toString());
    	}
    }
    
    
    private void showAlreadyCandidateContent(StringBuffer html, JobCandidate jobCand) {
    	Table alreadyCandTable = new BorderTable();
    	alreadyCandTable.setWidth(120);
    	Row row = alreadyCandTable.addRow();
    	Cell cell = row.addCell();
    	Font font = TextHelper.getFont("warnStdFont", this.getPhrase("phrase.apply.already.candidate"));
    	cell.addElement(font);
    	html.append(alreadyCandTable.toString());
    	html.append("<br>");
    }
    
    private Element getBackToJobListButton() {
    	Form form = new Form();
    	form.setMethod(Form.POST);
    	form.setAction("/hrs-public/public/" + ThreadProperties.getUriDomainId() + "/job/job_search_results.do");
    	Input prevHidden = new Input();
    	prevHidden.setType(Input.HIDDEN);
    	prevHidden.setName("usePrevJobCriteria");
    	prevHidden.setValue("true");
    	form.addElement(prevHidden);
		String html ="<input type=\"image\" src=\"" +
			this.getContextPath() +	"/dynagraphic/button.jpg?code=public.button.wide&caption="
		    + this.getPhrase("phrase.job.list.prev.search") + "\" border=\"0\" value=\"submit\" name=\"submit\" />";
		form.addElement(html);
    	return(form);
    }
    
    private String getJobSearchButton() {

    	Form form = new Form();
    	form.setMethod(Form.POST);
    	form.setAction("/hrs-public/public/" + ThreadProperties.getUriDomainId() + "/job/job_search.do");
    	
		String submitButton ="<input type=\"image\" src=\"" +
			this.getContextPath() +	"/dynagraphic/button.jpg?code=public.button.wide&caption=" 
		    + this.getPhrase("phrase.job.search.button") + "\" border=\"0\" value=\"submit\" name=\"submit\" />";
    	
    	form.addElement(submitButton);
    	
    	return(form.toString());
    }
    
        
    
	/**
	 * @return Returns the summary.
	 */
	public String getSummary() {
		return summary;
	}
	/**
	 * @param summary The summary to set.
	 */
	public void setSummary(String summary) {
		this.summary = summary;
	}
	
	
	/**
	 * @return Returns the jobId.
	 */
	public String getJobId() {
		return jobId;
	}
	/**
	 * @param jobId The jobId to set.
	 */
	public void setJobId(String jobId) {
		this.jobId = jobId;
	}
	
	
	/**
	 * @return Returns the formName.
	 */
	public String getFormName() {
		return formName;
	}
	/**
	 * @param formName The formName to set.
	 */
	public void setFormName(String formName) {
		this.formName = formName;
	}
	
	private boolean getShowJobApplication() {
	    return(RecruitConfig.getRecruitInstance().getShowJobApplicationOnPublicSite(ThreadProperties.getDomain()));
	}
}
